{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 假设\n",
    "\n",
    "本页概述了SymPy中的核心`Assumptions`假设系统。它解释了什么是核心假设体系，如何使用假设体系，以及不同的假设谓词意味着什么。\n",
    "\n",
    "注意: 本页介绍的核心假设系统也常被称为“旧假设”系统。另外还有一个“新的假设”系统，在其他地方也有描述。注意，这里描述的系统实际上是 SymPy 中广泛使用的系统。“新的假设”系统在 SymPy 中还没有真正被使用，“旧的假设”系统也不会被移除。在撰写本文(SymPy 1.7)时，仍然建议用户使用旧的假设系统。\n",
    "\n",
    "首先，我们考虑当取一个具体整数的平方根时会发生什么，例如2或-2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "4\n",
      "2\n",
      "True\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "from sympy import sqrt\n",
    "print(sqrt(2**2))\n",
    "print((-2)**2)\n",
    "x = 2\n",
    "print(sqrt(x**2))\n",
    "print(sqrt(x**2) == x)\n",
    "y = -2\n",
    "print(sqrt(y**2) == y)\n",
    "print(sqrt(y**2) == -y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这些例子证明了对于正数 x，我们有 $\\sqrt{x^2} = x$，而对于负数，我们有 $\\sqrt{x^2} = -x$。这似乎是显而易见的，但是当使用一个符号而不是一个明确的数字时，情况可能会更令人惊讶。例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\sqrt{x^{2}}$"
      ],
      "text/plain": [
       "sqrt(x**2)"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import Symbol, simplify\n",
    "x = Symbol('x')\n",
    "sqrt(x**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这看起来似乎应该简化为 x，但即使使用 simplify ()也不行:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\sqrt{x^{2}}$"
      ],
      "text/plain": [
       "sqrt(x**2)"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simplify(sqrt(x**2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是因为如果简化对 x 的任何可能值无效，SymPy 将拒绝简化这个表达式。默认情况下，符号 x 被认为只表示大致类似于任意复数的东西，这里显而易见的简化只对正实数有效。由于不知道 x 是正的，甚至不是真的，所以不可能简化这个表达式。\n",
    "我们可以告诉 SymPy，当创建符号时，一个符号代表一个正的实数，然后简化就会自动发生:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle y$"
      ],
      "text/plain": [
       "y"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = Symbol('y', positive=True)\n",
    "sqrt(y**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这就是 SymPy 中的“假设”的含义。如果符号 y 是用 positive = True 创建的，那么 SymPy 将假定它表示一个正实数，而不是任意的复数或者可能是无限的数。这个假设可以简化表达式，也可以允许其他操作工作。在创建一个符号时，尽可能精确地假设它通常是一个好主意。\n",
    "\n",
    "## (旧的)假设体系\n",
    "\n",
    "假设体系有两个方面。第一个方面是，我们可以在创建符号时声明对符号的假设。另一方面是，我们可以使用对应的 is _ * 属性查询任何表达式上的假设。例如:\n",
    "~~~python\n",
    ">>> x = Symbol('x', postive=True)\n",
    ">>> print(x.is_positive)\n",
    "True\n",
    "~~~"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以查询任何表达式的假设，而不仅仅是一个符号:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x^{2} + 1$"
      ],
      "text/plain": [
       "x**2 + 1"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x', positive=True)\n",
    "expr = 1 + x**2\n",
    "expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(expr.is_positive)\n",
    "print(expr.is_negative)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设查询中给出的值使用三值“模糊”逻辑。任何查询都可以返回 `True`、 `False` 或 `None`，其中 `None` 应被解释为结果未知。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x')\n",
    "y = Symbol('y', positive=True)\n",
    "z = Symbol('z', negative=True)\n",
    "print(x.is_positive)\n",
    "print(y.is_positive)\n",
    "print(z.is_positive)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 我们需要在上面的示例中使用 `print`，因为在 Python 解释器中缺省情况下不显示特殊值 `None`。\n",
    "\n",
    "有几个原因可以解释为什么假设查询可能会给出 `None`。查询可能像上面的 `x` 一样不可知。因为 `x` 没有任何假设，所以它粗略地表示一个任意的复数。任意复数可能是正实数，但也可能不是。没有进一步的信息，就无法解析查询 `x.is_positive`。\n",
    "\n",
    "假设查询可能给出 `None` 的另一个原因是，在许多情况下，确定一个表达式是否为正数的问题是不可判定的。这意味着通常不存在回答查询的算法。在某些情况下，算法或至少简单的检查是可能的，但是尚未实现，尽管可以将其添加到 SymPy 中。\n",
    "\n",
    "假设查询可能给出 `None` 的最后一个原因是假设系统不会非常努力地回答复杂的查询。该系统的目的是快速，并使用简单的启发式方法，以推断出一个真或假的答案在常见的情况下。例如，任何正项之和都是正的，所以:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x + y$"
      ],
      "text/plain": [
       "x + y"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import symbols\n",
    "x, y = symbols('x, y', positive=True)\n",
    "expr = x + y\n",
    "expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x + y\n",
    "expr.is_positive"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后一个例子特别简单，所以假设系统能够给出一个明确的答案。如果这个总和包含了正项或负项，那么这个问题就更难回答了:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left(x - 2\\right)^{2} + 1$"
      ],
      "text/plain": [
       "(x - 2)**2 + 1"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x', real=True)\n",
    "expr = 1 + (x - 2)**2\n",
    "expr\n",
    "(x - 2)**2 + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.is_positive"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x^{2} - 4 x + 5$"
      ],
      "text/plain": [
       "x**2 - 4*x + 5"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr2 = expr.expand()\n",
    "expr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "print(expr2.is_positive)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "理想情况下，最后一个示例给出的是 `True` 而不是 `None`，因为表达式对于 `x` 的任何实际值总是正值(并且 `x` 被假定为实值)。但是，假设系统的目的是提高效率: 预计许多更复杂的查询将无法完全解决。这是因为 sympy 主要在内部使用假设查询作为底层计算的一部分。使系统更加全面会使Sympy的速度减慢。\n",
    "\n",
    "注意，在给出不确定结果的模糊逻辑中，`None` 从来不矛盾。如果在解析查询时可以推断出一个确定的 `True` 或 `False` 结果，那么这比返回 `None` 要好。然而，`None` 的结果不是 bug。任何使用假设系统的代码都需要为处理任何查询的所有三种情况做好准备，并且不应假定总是会给出一个明确的答案。\n",
    "\n",
    "假设系统不仅仅是为了符号或复杂的表达式。它还可以用于普通 SymPy 整数和其他对象。假设谓词在 `Basic` 的任何实例上都是可用的，`Basic` 是大多数 SymPy 对象类的超类。普通 python 类型 `int` 不是 `Basic` 实例，不能用于查询假设谓词。我们可以使用 `sympify()` 或 `s` (SingletonRegistry) 来转换常规 Python 对象成为 SymPy 对象，然后可以使用假设系统:\n",
    "\n",
    "~~~python\n",
    "# 这样的调用会报异常\n",
    "from sympy import S\n",
    "x = 2\n",
    "x.is_positive\n",
    "~~~"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'sympy.core.numbers.Integer'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import S\n",
    "x = S(2)\n",
    "print(type(x))\n",
    "x.is_positive"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 陷阱: 找到了不相容的假设符号\n",
    "在 SymPy 中，可以用不同的名称声明两个符号，它们在结构平等下隐含地被认为是平等的:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x\n",
      "x\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x1 = Symbol('x')\n",
    "x2 = Symbol('x')\n",
    "print(x1)\n",
    "print(x2)\n",
    "print(x1 == x2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然而，如果这些符号有不同的假设，那么它们将被视为代表不同的符号:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x\n",
      "x\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "x1 = Symbol('x', positive=True)\n",
    "x2 = Symbol('x')\n",
    "print(x1)\n",
    "print(x2)\n",
    "print(x1 == x2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "简化表达式的一种方法是使用 `positfy()`函数，该函数将表达式中的所有符号替换为假设为 `positive = True` 的符号(除非与符号的任何现有假设相矛盾) :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle e^{\\sqrt{x^{2}}}$"
      ],
      "text/plain": [
       "exp(sqrt(x**2))"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import posify, exp\n",
    "x = Symbol('x')\n",
    "expr = exp(sqrt(x**2))\n",
    "expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(exp(_x), {_x: x})"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "posify(expr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle e^{x}$"
      ],
      "text/plain": [
       "exp(_x)"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr2, rep = posify(expr)\n",
    "expr2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Positfy ()`函数返回所有符号都被替换的表达式(这可能会导致简化) ，还返回一个 `dict`，它将新的符号映射到旧的符号，这些符号可以与 `subs()`一起使用。这是有用的，因为否则带有新符号的 `positive = True` 假设的新表达式将无法与旧表达式相比较:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr2 == exp(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle e^{x}$"
      ],
      "text/plain": [
       "exp(x)"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr2.subs(rep)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr2.subs(rep) == exp(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 对字符串输入应用假设\n",
    "\n",
    "我们已经看到了当 `Symbol` 或 `symbol()` 显式时如何设置假设。一个很自然的问题是，在什么样的情况下，我们可以给一个对象赋予假设？\n",
    "\n",
    "用户使用字符串作为 SymPy 函数的输入是很常见的(尽管 SymPy 开发人员普遍认为不应该这样做) ，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[-1, 1]"
      ]
     },
     "execution_count": 117,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import solve\n",
    "solve('x**2 - 1')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在明确创建符号时，可以分配一些假设，这些假设会影响求解的行为() :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1]"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x', positive=True)\n",
    "solve(x**2 - 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当使用字符串输入 SymPy 时，将创建表达式并隐式创建所有的符号，因此问题是如何指定假设？答案是，与其依赖于隐式字符串转换，不如显式地使用 `parse_expr()`函数，然后可以为符号提供假设，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x^{2} - 1$"
      ],
      "text/plain": [
       "x**2 - 1"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import parse_expr\n",
    "parse_expr('x**2 - 1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1]"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = parse_expr('x**2 -1', {'x': Symbol('x', positive=True)})\n",
    "solve(eq)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Solve()` 函数不同于其他高级 API， 它检查任何输入符号(未知数)的假设，并使用这些假设来调整其输出。否则，假设系统会影响低级评估，但不一定由高级 api 显式处理。\n",
    "\n",
    "## 谓词\n",
    "\n",
    "可以假定有许多不同的谓词用于符号，也可以查询它们用于表达式。在创建符号时，可以组合多个谓词。谓词的逻辑组合使用，因此，如果一个符号被声明为 `integer = True`，也被声明为 `positive = True`，那么它既是正数也是整数:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x', positive=True, integer=True)\n",
    "print(x.is_positive)\n",
    "print(x.is_integer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一个符号的全部已知谓词可以通过 assumptions0属性访问:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'positive': True,\n",
       " 'extended_real': True,\n",
       " 'extended_nonnegative': True,\n",
       " 'nonnegative': True,\n",
       " 'finite': True,\n",
       " 'nonpositive': False,\n",
       " 'imaginary': False,\n",
       " 'nonzero': True,\n",
       " 'extended_positive': True,\n",
       " 'extended_nonpositive': False,\n",
       " 'commutative': True,\n",
       " 'infinite': False,\n",
       " 'real': True,\n",
       " 'complex': True,\n",
       " 'hermitian': True,\n",
       " 'negative': False,\n",
       " 'zero': False,\n",
       " 'extended_negative': False,\n",
       " 'extended_nonzero': True,\n",
       " 'integer': True,\n",
       " 'rational': True,\n",
       " 'noninteger': False,\n",
       " 'irrational': False,\n",
       " 'algebraic': True,\n",
       " 'transcendental': False}"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.assumptions0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以看到，除了用于创建 `x` 的两个谓词之外，还列出了更多的谓词。这是因为假设系统可以从其他谓词的组合中推断出一些谓词。例如，如果一个符号被声明为 `positive = True`，那么可以推断它应该是 `negative = False`， 因为正数永远不可能是负数。类似地，如果一个符号是以 `integer = True` 创建的，那么就可以推断出它应该具有 `rational = True`，因为每个整数都是一个有理数。\n",
    "\n",
    "下面给出了可能的谓词及其定义的完整表格。\n",
    "\n",
    "| 断言 | 定义 | 影响 |\n",
    "|-----|------|-----|\n",
    "|交换的`commutative`| 可交换的表达式。一个交换表达式与乘法下的所有其他表达式相交换。如果一个表达式 `a` 具有 `commutative = True`，那么 `a * b == b * a` 成立对于任何其他表达式 `b` (即使 `b` 不是交换`connutative`的)。与所有其他假设不同，谓词交换必须始终是 `True` 或 `False`，并且永远不能是 `None`。与其他谓词不同的是，`Symbol('x')`中的交换性缺省值为 `True`。|  |\n",
    "|无限的`infinite`|无限表达式，如 oo,-oo 或者 zoo. | `==!finite` |\n",
    "|有限的`finite` | 一个有限的表达式。任何不是无限的表达式都被认为是有限的 | `==!infinite` |\n",
    "|厄尔米特的 `hermitian`| 厄米算符场的元素 |  |\n",
    "|反赫尔米特的 `antihermitian` | 反厄米算符场的元素 |  |\n",
    "|复数的 `complex` | 一个复数 `𝑧∈ℂ`。 任何数字形如 `x + iy` 其中 `x` 和 `y` 是实数 `real` 并且 $ i = \\sqrt{-1} $。所有 `complex`数字是有限的`finite`。包含了所有的实数`real`| `-> commutative` <br> `-> finite` |\n",
    "|代数的 `algebraic` | 代数数, $ 𝑧∈ \\overline{ℚ} $。 任何代数数都是非零有理数多项式的一个根 `𝑝(𝑧)∈ℚ[𝑧]`。所有的代数数 `algebraic`都是复数`complex`。一个代数数 `algebraic` 可能是或者不是实数`real`。包含所有的有理数`rational`| `-> complex` |\n",
    "|超越数`transcendental`|非代数的复数， $𝑧∈ℂ−\\overline{ℚ}$。所有超越数`transcendental`都是复数`complex`。一个超越数`transcendental`可能是或者不是实数`real`但一定不可能是有理数`ratinal`。 | `==(complex and !algebraic)` |\n",
    "|扩展实数的 `extended_real` | 扩展实数要么是实数要么是虚数 | `-> commutative` |\n",
    "|实数的 `real` |  `𝑥∈ℝ`， 所有`real`实数都是`finite`无限的和`complex`复数的。也包含了所有的有理数`rational`。| `-> complex` <br> `== (extended_real and finite)` <br> `==(negative or zero or positive)` <br> `-> hermitian` |\n",
    "|虚数的 `imaginary` | 所有的虚数都是复数而不是实数。另外要注意`zero`零在Sympy中不被认为是`imaginary`虚数的 | `-> complex` `->antihermitian` `-> !extended_real` |\n",
    "|有理数的 `rational` | 所有的有理数都是实数和代数。包括所有的整数 | `-> real` `-> algebraic` |\n",
    "|无理数的 `irrational` | 无理数 $ 𝑥∈ℝ−ℚ $ | `== (real & !rational)` |\n",
    "|整数 `integer` | 所有的整数都是有理数。包括零和所有素数，和数，偶数和奇数。 | `-> rational` |\n",
    "|非整数 `noninteger` | 非整数的扩展实数, $ x∈\\overline{ℝ}−ℤ | `== (extended_real & !integer)` |\n",
    "|偶数 `even` | 𝑒∈{2𝑘:𝑘∈ℤ} 所有偶数都是整数，偶数包含零 | `-> integer` `-> !odd` |\n",
    "|奇数 `odd` | 𝑜∈{2𝑘+1:𝑘∈ℤ} 所有奇数都是整数。 | `-> integer` `-> !even` |\n",
    "|素数 `prim` | 𝑝∈ℙ 所有的素数都是整数和正数 | `-> integer` `-> positive` |\n",
    "|合数 `composite` | 𝑐∈ℕ−(ℙ∪{1}) 合数是两个或更多整数的乘积。合数总是一个正数且整数但一定不是素数 | `-> (integer & positive & !prime)` <br> `!composite -> (!positive | !even | prime)`|\n",
    "|零 `zero` | 数字0, `zero = True` | `-> even & finite` `== (extended_nonnegegative & extended_nonpositive)` `==(nonnegative & nonpositive)` |\n",
    "|非零 `nonzero` | 𝑥∈ℝ−{0} 。 非零数总是实数且不为零 | `-> real` `== (extended_nonzero & finite)` |\n",
    "|扩展非零 `extended_nonzero` | 非零的扩展实数的一个成员，$ 𝑥∈ \\overline{ℝ}−{0} $ | `== (extended_real & !zero)`|\n",
    "|正数 `positive` | 𝑥∈ℝ,𝑥>0. 所有整数都是有限的所有 `oo`不是正数 | `== (nonnegative & nonzero)` `==(extended_positive & finite)` |\n",
    "|非负数 `nonnegative`| 𝑥∈ℝ,𝑥≥0 非负实数， 所有负数都是有限的所以 `-oo`不是非负数 | `==(nonpositive & nonzero)` `==(extended_negative) & finite)` |\n",
    "|非正数 `nonpositive` | 𝑥∈ℝ,𝑥≤0 所有非正数都是有限的，所以 `-oo`不是非正数 | `== (real & !positive)` `==(extended_nonpositive & finite)` |\n",
    "|扩展非负数 `extended_nonnegative` | $ 𝑥∈\\overline{ℝ},𝑥≥0 $ 扩展非负数要么是非负数要么是`oo`| `==(extended_real) & !extended_negative)` |\n",
    "|扩展负数 `extended_negative` | $𝑥∈\\overline{ℝ},𝑥<0$ 扩展负数要么是负数要么是`-oo` | `== extended_nonpositive & extended_nonzero)` |\n",
    "|扩展非正数 `extended_nonpositive` | $𝑥∈\\overline{ℝ},𝑥≤0$ 扩展非正数可以是非正数或者`-oo`| `== (extended_real & !extended_positive)` |\n",
    "\n",
    "## 上述定义的参考资料\n",
    "commutative 交换的\n",
    "https://en.wikipedia.org/wiki/Commutative_property\n",
    "\n",
    "infinite 无穷大\n",
    "https://en.wikipedia.org/wiki/Infinity\n",
    "\n",
    "antihermitian 厄米特\n",
    "https://en.wikipedia.org/wiki/Skew-Hermitian_matrix\n",
    "\n",
    "complex 复数\n",
    "https://en.wikipedia.org/wiki/Complex_number\n",
    "\n",
    "algebraic 代数\n",
    "https://en.wikipedia.org/wiki/Algebraic_number\n",
    "\n",
    "transcendental 超越数\n",
    "https://en.wikipedia.org/wiki/Transcendental_number\n",
    "\n",
    "extended_real 扩展实数\n",
    "https://en.wikipedia.org/wiki/Extended_real_number_line\n",
    "\n",
    "real 实数\n",
    "https://en.wikipedia.org/wiki/Real_number\n",
    "\n",
    "imaginary 虚数\n",
    "https://en.wikipedia.org/wiki/Imaginary_number\n",
    "\n",
    "rational 有理数\n",
    "https://en.wikipedia.org/wiki/Rational_number\n",
    "\n",
    "irrational 无理数\n",
    "https://en.wikipedia.org/wiki/Irrational_number\n",
    "\n",
    "integer 整数\n",
    "https://en.wikipedia.org/wiki/Integer\n",
    "\n",
    "parity 平价\n",
    "https://en.wikipedia.org/wiki/Parity_(mathematics)\n",
    "\n",
    "prime 质数\n",
    "https://en.wikipedia.org/wiki/Prime_number\n",
    "\n",
    "composite 合成的\n",
    "https://en.wikipedia.org/wiki/Composite_number\n",
    "\n",
    "zero 零\n",
    "https://en.wikipedia.org/wiki/0\n",
    "\n",
    "positive 正数\n",
    "https://en.wikipedia.org/wiki/Positive_real_numbers\n",
    "\n",
    "negative 负数\n",
    "https://en.wikipedia.org/wiki/Negative_number\n",
    "\n",
    "## 影响\n",
    "\n",
    "假设系统使用推理规则来推断新的谓词，这些谓词超出了创建符号时直接指定的范围:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x', real=True, negative=False, zero=False)\n",
    "x.is_positive"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "尽管`x`没有被明确的声明为`postive`, 但可以从给定的谓词中推断出它。 具体来说一个推理的规则是 `real == negative | zero | positive` 所以如果 `real` 是 `True` 并且 `negative` 和 `zero` 都是 `False` 那么 `positive` 必然是 `True`。 \n",
    "\n",
    "在实践中，假设推理规则意味着没有必要包括多余的谓词，例如，一个正实数可以简单地声明为 `positive`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x1 = Symbol('x1', positive=True, real=True)\n",
    "x2 = Symbol('x2', positive=True)\n",
    "print(x1.is_real)\n",
    "print(x2.is_real)\n",
    "print(x1.assumptions0 == x2.assumptions0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "合并不一致的谓词会产生错误:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "ename": "InconsistentAssumptions",
     "evalue": "{\n\talgebraic: False,\n\tcommutative: False,\n\tcomplex: False,\n\tcomposite: False,\n\teven: False,\n\textended_negative: False,\n\textended_nonnegative: False,\n\textended_nonpositive: False,\n\textended_nonzero: False,\n\textended_positive: False,\n\textended_real: False,\n\timaginary: False,\n\tinteger: False,\n\tirrational: False,\n\tnegative: False,\n\tnoninteger: False,\n\tnonnegative: False,\n\tnonpositive: False,\n\tnonzero: False,\n\todd: False,\n\tpositive: False,\n\tprime: False,\n\trational: False,\n\treal: False,\n\ttranscendental: False,\n\tzero: False}, real=True",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mInconsistentAssumptions\u001b[0m                   Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-125-350d612e2468>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mSymbol\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'x'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcommutative\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreal\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/symbol.py\u001b[0m in \u001b[0;36m__new__\u001b[0;34m(cls, name, **assumptions)\u001b[0m\n\u001b[1;32m    270\u001b[0m         \"\"\"\n\u001b[1;32m    271\u001b[0m         \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_sanitize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0massumptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 272\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mSymbol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__xnew_cached_\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0massumptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    273\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    274\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__new_stage2__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0massumptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/cache.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m     70\u001b[0m         \u001b[0;32mdef\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     71\u001b[0m             \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 72\u001b[0;31m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     73\u001b[0m             \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     74\u001b[0m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/symbol.py\u001b[0m in \u001b[0;36m__new_stage2__\u001b[0;34m(cls, name, **assumptions)\u001b[0m\n\u001b[1;32m    292\u001b[0m         \u001b[0mis_commutative\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfuzzy_bool\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0massumptions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'commutative'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    293\u001b[0m         \u001b[0massumptions\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'commutative'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mis_commutative\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 294\u001b[0;31m         \u001b[0mobj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_assumptions\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mStdFactKB\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0massumptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    295\u001b[0m         \u001b[0mobj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_assumptions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_generator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtmp_asm_copy\u001b[0m  \u001b[0;31m# Issue #8873\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    296\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mobj\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/assumptions.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, facts)\u001b[0m\n\u001b[1;32m    432\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_generator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfacts\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgenerator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    433\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mfacts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 434\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdeduce_all_facts\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfacts\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    435\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    436\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/facts.py\u001b[0m in \u001b[0;36mdeduce_all_facts\u001b[0;34m(self, facts)\u001b[0m\n\u001b[1;32m    518\u001b[0m             \u001b[0;31m# --- alpha chains ---\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    519\u001b[0m             \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfacts\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 520\u001b[0;31m                 \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_tell\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    521\u001b[0m                     \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    522\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/facts.py\u001b[0m in \u001b[0;36m_tell\u001b[0;34m(self, k, v)\u001b[0m\n\u001b[1;32m    489\u001b[0m                 \u001b[0;32mreturn\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    490\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 491\u001b[0;31m                 \u001b[0;32mraise\u001b[0m \u001b[0mInconsistentAssumptions\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    492\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    493\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mInconsistentAssumptions\u001b[0m: {\n\talgebraic: False,\n\tcommutative: False,\n\tcomplex: False,\n\tcomposite: False,\n\teven: False,\n\textended_negative: False,\n\textended_nonnegative: False,\n\textended_nonpositive: False,\n\textended_nonzero: False,\n\textended_positive: False,\n\textended_real: False,\n\timaginary: False,\n\tinteger: False,\n\tirrational: False,\n\tnegative: False,\n\tnoninteger: False,\n\tnonnegative: False,\n\tnonpositive: False,\n\tnonzero: False,\n\todd: False,\n\tpositive: False,\n\tprime: False,\n\trational: False,\n\treal: False,\n\ttranscendental: False,\n\tzero: False}, real=True"
     ]
    }
   ],
   "source": [
    "x = Symbol('x', commutative=False, real=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 谓词的解释\n",
    "\n",
    "尽管谓词是在上面的表中定义的，但还是值得花一些时间来考虑如何解释它们。首先，谓词名称所指的许多概念，如`zero`、`prime`、`rational`等，在数学上有一个基本含义，但也可以有更一般的含义。例如，在处理矩阵时，所有零的矩阵可以称为`zero`。假设系统中的谓词不允许任何这样的泛化。谓词0是严格保留给纯数字0的。相反， 矩阵有一个 `is_zero_matrix()`属性用于此目的(尽管这个属性并不严格地属于假设系统) :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "from sympy import Matrix\n",
    "M = Matrix([[0, 0], [0, 0]])\n",
    "print(M.is_zero)\n",
    "print(M.is_zero_matrix)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "类似的，还有一些整数的推广，比如高斯整数，它们有着不同的素数概念。假设系统中的素数谓词不包括这些高斯整数，只严格地指标准素数 ℙ = {2,3,5,7,11，...... }。同样，整数只表示整数的标准概念 ℤ = {0，± 1，± 2， ...... }。 有理数只是有理数的标准概念ℚ，如此等等。\n",
    "\n",
    "这些谓词建立子集的方案，例如以复数开头的链，这些复数被认为是实数的超集，而实数又是有理数的超集，等等。子集的链 ℤ⊂ℚ⊂ℝ⊂ℂ 与假设系统中的含义链相对应: integer -> rational -> real -> complex\n",
    "\n",
    "没有明确附加任何假设的`vanilla`符号不知道属于这些集合中的任何一个，甚至不知道是有限的:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'commutative': True}\n",
      "True\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x')\n",
    "print(x.assumptions0)\n",
    "print(x.is_commutative)\n",
    "print(x.is_rational)\n",
    "print(x.is_complex)\n",
    "print(x.is_real)\n",
    "print(x.is_integer)\n",
    "print(x.is_finite)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于 SymPy 来说，很难知道它能用这样一个甚至不知道是有限的或复杂的符号做什么，所以通常最好明确地对这个符号给出一些假设。SymPy 的许多部分将隐式地将这样的符号视为复杂的，在某些情况下，SymPy 将允许操作，而这些操作在严格意义上是无效的，因为 `x` 并不知道是有限的。在正式意义上，虽然很少能感知`vanilla`符号的象征，使涉及它的计算操作困难。\n",
    "\n",
    "定义一个符号可以产生很大的不同。例如，如果我们将符号声明为整数，那么这意味着一组其他谓词将有助于进一步操作:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Integer': True, 'commutative': True}"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = Symbol('n', Integer=True)\n",
    "n.assumptions0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这些假设可以导致非常明显的简化，例如 integer = True 能够进行如下推理, 区别于未提供任何类型信息:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sin(pi*n1)\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "from sympy import sin, pi\n",
    "n1 = Symbol('n1')\n",
    "n2 = Symbol('n2', integer=True)\n",
    "print(sin(n1 * pi))\n",
    "print(sin(n2 * pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "能够用0替换整个需要化简的表达式, 已经是最好的化简了！\n",
    "\n",
    "通常建议对任何符号设置尽可能多的假设，以便尽可能简化表达式。一个常见的误解导致用一个假谓词来定义一个符号，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "None\n",
      "None\n",
      "None\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x', negative=False)\n",
    "print(x.is_negative)\n",
    "print(x.is_nonnegative)\n",
    "print(x.is_real)\n",
    "print(x.is_complex)\n",
    "print(x.is_finite)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果意图是说 x 是一个不是正数的实数，那么需要明确说明。在已知符号是真实的上下文中，谓词 positive = False 变得更有意义:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "True\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x', real=True, negative=False)\n",
    "print(x.is_negative)\n",
    "print(x.is_nonnegative)\n",
    "print(x.is_real)\n",
    "print(x.is_complex)\n",
    "print(x.is_finite)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "被声明为 `Symbol('x', real=True, negative=False)`的符号等价于被声明为 `Symbol('x', nonegative=True)`的符号。简单地将一个符号声明为 `Symbol('x', positive=False)`并不允许假设系统对它做出很多结论，因为一个普通的符号并不知道是有限的，甚至是复杂的。\n",
    "\n",
    "与 `Symbol('x', complex=True)`和 `Symbol('x', real=False)`相关的混淆出现了。通常，当这两者中的任何一个被使用的时候，它们都不是真正想要的。首先要理解的是，所有实数都是复数，所以用 `real = True` 创建的符号也会有 `complex = True`，而用 `complex = True` 创建的符号不会有 `real = False`。如果目的是创建一个不是实数的复数，那么它应该是 `Symbol ('x'，complex = True，real = False)`。另一方面，仅仅声明 `real = False` 并不足以得出`complex = True` 的结论，因为知道它不是一个实数并不能告诉我们它是否是有限的，或者它是否是某种完全不同于复数的对象。\n",
    "\n",
    "`vanilla`符号的定义是不知道它是否是`有限`的等等，没有明确的定义它应该代表什么。人们很容易认为它是一个”任意复数或可能是无穷之一”，但是没有办法查询任意(非符号)表达式以确定它是否符合这些标准。重要的是要记住，在 SymPy 代码库和潜在的下游库中，可以找到许多其他类型的数学对象，这些对象也可能具有交换性`commutative = True`，同时与普通数字非常不同(在这种情况下，甚至 SymPy 的标准无穷被认为是“普通的”)。\n",
    "\n",
    "默认情况下为符号应用的唯一谓词是可交换`commutative`的。我们也可以声明一个符号是非交换的，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x y + y x$"
      ],
      "text/plain": [
       "x*y + y*x"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, y = symbols('x, y', commutative=False)\n",
    "z = Symbol('z')\n",
    "x*y + y*x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 2 z x$"
      ],
      "text/plain": [
       "2*z*x"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x*z + z*x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意，由于 `x` 和 `y` 都是非交换的 `x` 和 `y` 不能相互代换，所以 `x * y != y * x` 另一方面，因为 `z` 是交换的，即使 `x` 是非交换的。\n",
    "\n",
    "对`vanilla`符号的解释并不清楚，但是对带有 `commutative = False` 的表达式的解释却完全模糊。这样的表达式不一定是复数或扩展实数，也不一定是标准无穷(即使 `zoo` 是交换的)。关于这样一个表达式到底代表什么，我们几乎没有什么可说的了。\n",
    "\n",
    "## 其它is_*属性\n",
    "\n",
    "SymPy 中有许多名称以 `is_` 开头的属性和属性，它们看起来类似于(旧的)假设系统中使用的属性，但实际上并不是假设系统的一部分。其中一些具有与上面所示的 `is_zero_matrix()` 属性等假设系统相似的含义和用法。另一个例子是集合的 `is_empty` 属性:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left\\{1, 2\\right\\}$"
      ],
      "text/plain": [
       "FiniteSet(1, 2)"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import FiniteSet, Intersection\n",
    "S1 = FiniteSet(1, 2)\n",
    "S1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left\\{1\\right\\} \\cap \\left\\{x\\right\\}$"
      ],
      "text/plain": [
       "Intersection(FiniteSet(1), FiniteSet(x))"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "S2 = Intersection(FiniteSet(1), FiniteSet(Symbol('x')))\n",
    "S2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "print(S2.is_empty)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`is_empty` 属性给出一个 `fuzzy-bool`，表示一个 `Set` 是否是空集。在 `S2` 的例子中，如果不知道 `x` 是否等于1，就不可能知道集合是否为空，因此 `S2.is_empty` 给出 `None`。集合的 `is_empty` 属性与假设系统中的 `is_zero` 属性有着类似的作用: `is_empty` 通常只适用于 `EmptySet` 对象，但是能够区分是 `is_empty = False` 和 `is_empty = None` 两种情况仍然是有用的。\n",
    "\n",
    "虽然 `is_zero_matrix` 和 `is_empty` 用于类似的目的假设属性，如 `is_zero`，他们不是(旧的)假设系统的一部分。没有相关的推理规则连接，例如 `Set.is_empty` 和 `Set.is_finite_set`，因为推理规则是(旧的)假设系统的一部分，该系统只处理上表中列出的谓词。声明一个 `MatrixSymbol` 是不可能的，比如 `zero_matrix = False`，也没有 `SetSymbol` 类，但是如果有的话，它就不会有一个理解像 `empty = False` 这样的谓词的系统。\n",
    "\n",
    "`is_zero_matrix()` ，`is_empty`，这些属性它们涉及到表达式的语义方面，所以与假设系统的性质相似。还有许多其他关注结构方面的属性，比如 `is_number`，`is_number()` ，`is_comparable()`。由于这些性质指的是一个表达式的结构方面，它们总是给出 `True` 或 `False` ，而不是一个模糊的布尔值，也有可能是 `None` 。大写的属性如 `is_number` 通常是 `isinstance` 检查的简写形式，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "from sympy import Number, Rational\n",
    "x = Rational(1, 2)\n",
    "print(isinstance(x, Number))\n",
    "print(x.is_Number)\n",
    "y = Symbol('y', rational=True)\n",
    "print(isinstance(y, Number))\n",
    "print(y.is_Number)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Number` 类是 `Integer` 、 `Rational` 和 `Float` 的超类，因此 `Number` 的任何实例都表示一个具有已知值的具体数字。像 `y` 这样用 `rational = True` 声明的符号可能表示与 `x` 相同的值，但它不是一个具有已知值的具体数字，因此这是一个结构上的区别，而不是语义上的区别。类似 `is_Number` 的属性有时会在 SymPy 中代替 `isinstance (obj，Number)` ，因为它们在循环导入方面没有问题，并且检查 `x.is_Number` 可以比调用 `isinstance` 更快。\n",
    "\n",
    "`is_number` (小写)属性与 `is_Number` 非常不同。对于任何可以用 `evalf()` 进行数值求值为浮点复数的表达式， `is_number` 属性为 `True`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\sqrt{2} + i$"
      ],
      "text/plain": [
       "sqrt(2) + I"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import I\n",
    "expr1 = I + sqrt(2)\n",
    "expr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 1.4142135623731 + 1.0 i$"
      ],
      "text/plain": [
       "1.4142135623731 + 1.0*I"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(expr1.is_number)\n",
    "expr1.evalf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x + 1$"
      ],
      "text/plain": [
       "x + 1"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x')\n",
    "expr2 = 1 + x\n",
    "expr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x + 1.0$"
      ],
      "text/plain": [
       "x + 1.0"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(expr2.is_number)\n",
    "expr2.evalf()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "检查 `expr.is_number` 的主要原因是预测对 `evalf()` 的调用是否会完全计算结果。`is_comparable()` 属性类似于 `is_number()` ，只是如果 `is_comparable` 给出 `True` ，那么表达式保证在数值上计算为一个真实的 `Float` 。当 `a.is_comparable` 和 `b.is_comparable` 时，不等式 `a < b` 应该像 `a.evalf() < b.evalf()`那样可以解析。\n",
    "\n",
    "SymPy 中的完整 `is_*` 属性、属性和方法集非常大。但是必须清楚的是，只有上面谓词表中列出的那些实际上是假设系统的一部分。只有实施假设系统的机制所涉及的那些属性，下文将予以解释。\n",
    "\n",
    "## 实现假设处理程序\n",
    "\n",
    "现在我们将通过一个例子来说明如何实现 SymPy 符号函数，以便我们可以看到旧的假设是如何在内部使用的。SymPy 已经为所有复数定义了 `exp` 函数，但是我们将定义一个 `expreal` 函数，该函数仅限于实参。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sympy import Function\n",
    "from sympy.core.logic import fuzzy_and, fuzzy_or\n",
    "\n",
    "\n",
    "class expreal(Function):\n",
    "    \"\"\"exponential function E**x restricted to the extended reals\"\"\"\n",
    "\n",
    "    is_extended_nonnegative = True\n",
    "\n",
    "    @classmethod\n",
    "    def eval(cls, x):\n",
    "        # Validate the argument\n",
    "        if x.is_extended_real is False:\n",
    "            raise ValueError(\"non-real argument to expreal\")\n",
    "        # Evaluate for special values\n",
    "        if x.is_zero:\n",
    "            return S.One\n",
    "        elif x.is_infinite:\n",
    "            if x.is_extended_negative:\n",
    "                return S.Zero\n",
    "            elif x.is_extended_positive:\n",
    "                return S.Infinity\n",
    "\n",
    "    @property\n",
    "    def x(self):\n",
    "        return self.args[0]\n",
    "\n",
    "    def _eval_is_finite(self):\n",
    "        return fuzzy_or([self.x.is_real, self.x.is_extended_nonpositive])\n",
    "\n",
    "    def _eval_is_algebraic(self):\n",
    "        if fuzzy_and([self.x.is_rational, self.x.is_nonzero]):\n",
    "            return False\n",
    "\n",
    "    def _eval_is_integer(self):\n",
    "        if self.x.is_zero:\n",
    "            return True\n",
    "\n",
    "    def _eval_is_zero(self):\n",
    "        return fuzzy_and([self.x.is_infinite, self.x.is_extended_negative])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Eval` 方法用于获取函数的特殊值，以便我们可以返回一个不同的对象，如果这是一个简化的对象。当 `expreal(x)` 被称为 `expreal.__new__` 方法(在超类 `Function` 中定义)将调用 `expreal.eval(x)`。如果 `expreal.eval` 返回的内容不是 `None` ，那么它将被返回，而不是未经计算的 `expreal(x)` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(1 \\right)}$"
      ],
      "text/plain": [
       "expreal(1)"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import oo\n",
    "expreal(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 1$"
      ],
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 0$"
      ],
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(-oo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\infty$"
      ],
      "text/plain": [
       "oo"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(oo)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意 `expreal.eval` 方法不使用 `==` 来比较参数。使用假设系统查询参数的属性来验证特殊值。这意味着 `expreal` 方法也可以计算具有匹配属性的不同表达式。例如: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle x$"
      ],
      "text/plain": [
       "x"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x', extended_negative=True, infinite=True)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 0$"
      ],
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当然，假设系统只能解析有限数量的特殊值，所以大多数 `eval` 方法也会用 `==` 来检查一些特殊值，但最好是检查，比如 `x.is_zero` 而不是 `x==0`。\n",
    "\n",
    "还要注意 `expreal.eval` 方法验证了参数是实数。 我们需要允许 `±∞` 作为参数来 `expreal`, 所以我们检查 `extended_real` 而不是 `real` 。如果参数不是实数的，那么我们会产生一个错误:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "non-real argument to expreal",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-68-0fce53b6e95e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexpreal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mI\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/cache.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m     70\u001b[0m         \u001b[0;32mdef\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     71\u001b[0m             \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 72\u001b[0;31m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     73\u001b[0m             \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     74\u001b[0m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/function.py\u001b[0m in \u001b[0;36m__new__\u001b[0;34m(cls, *args, **options)\u001b[0m\n\u001b[1;32m    471\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    472\u001b[0m         \u001b[0mevaluate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'evaluate'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mglobal_parameters\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevaluate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 473\u001b[0;31m         \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__new__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    474\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mevaluate\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    475\u001b[0m             \u001b[0mpr2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_should_evalf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/cache.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m     70\u001b[0m         \u001b[0;32mdef\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     71\u001b[0m             \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 72\u001b[0;31m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     73\u001b[0m             \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     74\u001b[0m                 \u001b[0mretval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/sympy/core/function.py\u001b[0m in \u001b[0;36m__new__\u001b[0;34m(cls, *args, **options)\u001b[0m\n\u001b[1;32m    283\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    284\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mevaluate\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 285\u001b[0;31m             \u001b[0mevaluated\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0meval\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    286\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mevaluated\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    287\u001b[0m                 \u001b[0;32mreturn\u001b[0m \u001b[0mevaluated\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-56-f58c86e2adc8>\u001b[0m in \u001b[0;36meval\u001b[0;34m(cls, x)\u001b[0m\n\u001b[1;32m     12\u001b[0m         \u001b[0;31m# Validate the argument\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_extended_real\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"non-real argument to expreal\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     15\u001b[0m         \u001b[0;31m# Evaluate for special values\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_zero\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: non-real argument to expreal"
     ]
    }
   ],
   "source": [
    "expreal(I)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "重要的是，我们检查 `x.is_extended_real is False` 而非 `not x.is_extended_real`，这意味着我们只有在参数肯定不是 `extended_real` 时才会拒绝它: 如果 `x.is_extended_real` 给 `None`，那么参数就不会被拒绝。允许 `x.is_extended_real = None` 的第一个原因是为了使用 `vanilla` 符号可以与 `expreal` 一起使用。第二个原因是，即使在参数确实是实数的情况下，假设查询也可以给出 `None`，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(x \\right)}$"
      ],
      "text/plain": [
       "expreal(x)"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = Symbol('x')\n",
    "print(x.is_extended_real)\n",
    "expreal(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\sqrt{2}$"
      ],
      "text/plain": [
       "sqrt(2)"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr = (1 + I)/sqrt(2) + (1 - I)/sqrt(2)\n",
    "print(expr.is_extended_real)\n",
    "None\n",
    "expr.expand()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.expand().is_extended_real"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(\\frac{\\sqrt{2} \\left(1 - i\\right)}{2} + \\frac{\\sqrt{2} \\left(1 + i\\right)}{2} \\right)}$"
      ],
      "text/plain": [
       "expreal(sqrt(2)*(1 - I)/2 + sqrt(2)*(1 + I)/2)"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(expr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "验证 `expreal.eval` 中的参数确实意味着传递 `evaluate = False` 时不会验证它，但是没有更好的地方来执行验证:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(i \\right)}$"
      ],
      "text/plain": [
       "expreal(I)"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(I, evaluate=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`expreal` 类上的 `extended_nonnegative` 类属性和`expreal` 实例的 `_eval_is_*` 方法假设系统中实现查询:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(2 \\right)}$"
      ],
      "text/plain": [
       "expreal(2)"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "False\n",
      "False\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(-\\infty \\right)}$"
      ],
      "text/plain": [
       "expreal(-oo)"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(expreal(2).is_finite)\n",
    "print(expreal(2).is_integer)\n",
    "print(expreal(2).is_rational)\n",
    "print(expreal(2).is_algebraic)\n",
    "z = expreal(-oo, evaluate=False)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\operatorname{expreal}{\\left(x \\right)}$"
      ],
      "text/plain": [
       "expreal(x)"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(z.is_integer)\n",
    "x = Symbol('x', real=True)\n",
    "expreal(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expreal(x).is_nonnegative"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设系统解决了 `expreal(2).is_finite` 之类的查询。使用相应的处理程序 `expreal.__eval_is_finite`，以及蕴涵规则。例如，众所周知 `expreal(2).is_rational` 是 `False`，因为 `expreal(2)._eval_is_algebraic` 返回 `False` 并且存在一个蕴涵规则 `rational-> algebraic`。这意味着在这种情况下， `is_rational` 查询可以通过 `_eval_is_algebraic` 处理程序来解决。实际上，最好不要为每个可能的谓词实现假设处理程序， 而是尝试并确定一组最小的处理程序， 这些处理程序可以用尽可能少的检查来解决尽可能多的查询。\n",
    "\n",
    "另一点需要注意的是 `_eval_is_*` 方法只对参数 `x` 进行假设查询，不对 `self` 进行任何假设查询。对同一对象的递归假设查询将干扰假设含义解析器，可能导致非确定性行为，因此不应该使用它们(SymPy 代码库中有这样的例子，但应该删除它们)。\n",
    "\n",
    "许多 `expreal` 方法隐式返回 `None` 。这是假设系统中的一个常见模式。 `Eval` 方法和 `eval_is_*` 方法都可以返回 `None` ，并且通常会返回 `None` 。结束时没有返回语句的 Python 函数将隐式返回 `None` 。我们利用这一点，从 `if` 语句中删除了许多 `else` 子句，并允许隐式返回 `None` 。当跟踪这些方法的控制流时，重要的是要首先记住，任何被查询的属性都可以给出 `True` 、 `False` 或 `None` ，而且如果所有条件失败，任何函数都将隐式返回 `None` 。\n",
    "\n",
    "## 假设系统的机制\n",
    "\n",
    "本节描述可能在未来 SymPy 版本中更改的内部细节。\n",
    "\n",
    "本节将解释假设系统的内部工作原理。重要的是要理解这些内部工作是实现细节，并且可能从一个 SymPy 版本更改为另一个。这个解释是写在 SymPy 1.7中的。尽管(旧的)假设系统有许多局限性(在下一节中讨论) ，但它是一个成熟的系统，在 SymPy 中得到了广泛的应用，并且已经针对其当前的使用进行了优化。在大多数 SymPy 操作中，隐含地使用假设系统来控制基本表达式的求值。\n",
    "\n",
    "在 SymPy 过程中实现假设系统有几个阶段，这些阶段导致对假设系统中的单个查询进行评估。简单地说，这些是:\n",
    "\n",
    "1. 在导入时，对 `sympy/core/assumptions.py` 中定义的假设规则进行规范化处理，以便有效地应用蕴涵规则。当甚至在定义 `Basic` 类之前导入 SymPy 时，就会发生一次这种情况。\n",
    "2. `ManagedProperties` 元类定义为所有 `Basic` 子类的元类。该类将对每个 `Basic` 子类进行后处理，以添加假设查询所需的相关属性。这还将 `default_assumptions` 属性添加到类中。每次定义 `Basic` 子类时都会发生这种情况。\n",
    "3. 每个 `Basic` 实例最初都使用 `default_premissions` 类属性。当在第一个实例中对 `Basic` 实例进行假设查询时，查询将从该类的 `default_assumptions` 中回答。\n",
    "4. 如果类的 `default_assuments` 查询中没有用于假设的缓存值，那么将复制默认假设，为实例创建一个假设缓存。然后调用 `_ask()` 函数来解析查询，查询将首先调用相关的实例处理程序 `_eval_is` 方法。如果处理程序返回 `non-None`，那么结果将被缓存并返回。\n",
    "5. 如果该处理程序不存在或给出 `None`，则尝试暗示解决程序。这将枚举(以随机顺序)所有可能用于根据蕴含规则解析查询的谓词组合。在每种情况下，都会调用处理程序 `_eval_is` 方法，以查看它是否给出 `non-None`。如果处理程序和隐含规则的任何组合导致查询的确定结果，那么该结果将缓存在实例缓存中并返回。\n",
    "6. 最后，如果影响解析程序无法解析查询，则该查询被认为是不可解析的。查询的 `None` 值缓存在实例缓存中并返回。\n",
    "\n",
    "在 `sympy/core/assumptions.py` 中定义的假设规则以类似于 `real == negative | zero | positive` 的形式给出。当这个模块被导入时，它们被转换成一个名为 `_assumption_rules` 的 `FactRules` 实例。这将隐含规则预处理为可用于隐含解析器的 \"a\" 和 \"b\"规则的形式。在 `sympy/core/facts.py` 代码中对此进行了解释。我们可以像这样直接访问这个内部对象(省略完整输出) :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'algebraic',\n",
       " 'antihermitian',\n",
       " 'commutative',\n",
       " 'complex',\n",
       " 'composite',\n",
       " 'even',\n",
       " 'extended_negative',\n",
       " 'extended_nonnegative',\n",
       " 'extended_nonpositive',\n",
       " 'extended_nonzero',\n",
       " 'extended_positive',\n",
       " 'extended_real',\n",
       " 'finite',\n",
       " 'hermitian',\n",
       " 'imaginary',\n",
       " 'infinite',\n",
       " 'integer',\n",
       " 'irrational',\n",
       " 'negative',\n",
       " 'noninteger',\n",
       " 'nonnegative',\n",
       " 'nonpositive',\n",
       " 'nonzero',\n",
       " 'odd',\n",
       " 'positive',\n",
       " 'prime',\n",
       " 'rational',\n",
       " 'real',\n",
       " 'transcendental',\n",
       " 'zero'}"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy.core.assumptions import _assume_rules\n",
    "_assume_rules.defined_facts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "defaultdict(set,\n",
       "            {('extended_nonpositive', True): {('commutative', True),\n",
       "              ('composite', False),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False)},\n",
       "             ('finite', False): {('algebraic', False),\n",
       "              ('complex', False),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', True),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('zero', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('even', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_nonpositive', True),\n",
       "              ('extended_nonzero', False),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', True),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', True),\n",
       "              ('nonpositive', True),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False)},\n",
       "             ('nonzero', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('real', True),\n",
       "              ('zero', False)},\n",
       "             ('irrational', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', False),\n",
       "              ('noninteger', True),\n",
       "              ('nonzero', True),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', True),\n",
       "              ('zero', False)},\n",
       "             ('nonzero', False): {('composite', False),\n",
       "              ('negative', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False)},\n",
       "             ('hermitian', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('zero', False)},\n",
       "             ('extended_nonpositive', False): {('extended_negative', False),\n",
       "              ('negative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('zero', False)},\n",
       "             ('integer', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('irrational', False),\n",
       "              ('noninteger', False),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False)},\n",
       "             ('positive', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_positive', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', True),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', True),\n",
       "              ('real', True),\n",
       "              ('zero', False)},\n",
       "             ('extended_nonnegative', True): {('commutative', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('negative', False)},\n",
       "             ('prime', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_positive', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', True),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', True),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', True),\n",
       "              ('positive', True),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('noninteger', True): {('commutative', True),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('integer', False),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('nonnegative', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('negative', False),\n",
       "              ('real', True)},\n",
       "             ('imaginary', True): {('antihermitian', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', False),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', False),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', False),\n",
       "              ('finite', True),\n",
       "              ('infinite', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('zero', False)},\n",
       "             ('complex', True): {('commutative', True),\n",
       "              ('finite', True),\n",
       "              ('infinite', False)},\n",
       "             ('extended_real', True): {('commutative', True),\n",
       "              ('imaginary', False)},\n",
       "             ('algebraic', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('integer', False),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('zero', False)},\n",
       "             ('commutative', False): {('algebraic', False),\n",
       "              ('complex', False),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', False),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', False),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', False),\n",
       "              ('imaginary', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('infinite', True): {('algebraic', False),\n",
       "              ('complex', False),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('finite', False),\n",
       "              ('imaginary', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('rational', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('irrational', False),\n",
       "              ('real', True),\n",
       "              ('transcendental', False)},\n",
       "             ('odd', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('even', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', True),\n",
       "              ('irrational', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonzero', True),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('nonnegative', False): {('composite', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('extended_negative', True): {('commutative', True),\n",
       "              ('composite', False),\n",
       "              ('extended_nonnegative', False),\n",
       "              ('extended_nonpositive', True),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('nonnegative', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('real', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False)},\n",
       "             ('extended_nonzero', True): {('commutative', True),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('zero', False)},\n",
       "             ('transcendental', True): {('algebraic', False),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('finite', True),\n",
       "              ('infinite', False),\n",
       "              ('integer', False),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('zero', False)},\n",
       "             ('extended_nonzero', False): {('composite', False),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_positive', False),\n",
       "              ('negative', False),\n",
       "              ('nonzero', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False)},\n",
       "             ('complex', False): {('algebraic', False),\n",
       "              ('composite', False),\n",
       "              ('even', False),\n",
       "              ('imaginary', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('nonpositive', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('extended_nonpositive', True),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('real', True)},\n",
       "             ('integer', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('even', False): {('zero', False)},\n",
       "             ('rational', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('integer', False),\n",
       "              ('odd', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('real', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('zero', False)},\n",
       "             ('negative', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('composite', False),\n",
       "              ('extended_negative', True),\n",
       "              ('extended_nonnegative', False),\n",
       "              ('extended_nonpositive', True),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_positive', False),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', True),\n",
       "              ('nonzero', True),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('real', True),\n",
       "              ('zero', False)},\n",
       "             ('composite', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_positive', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', True),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', True),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', True),\n",
       "              ('positive', True),\n",
       "              ('prime', False),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False),\n",
       "              ('zero', False)},\n",
       "             ('even', True): {('algebraic', True),\n",
       "              ('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('extended_real', True),\n",
       "              ('finite', True),\n",
       "              ('hermitian', True),\n",
       "              ('imaginary', False),\n",
       "              ('infinite', False),\n",
       "              ('integer', True),\n",
       "              ('irrational', False),\n",
       "              ('noninteger', False),\n",
       "              ('odd', False),\n",
       "              ('rational', True),\n",
       "              ('real', True),\n",
       "              ('transcendental', False)},\n",
       "             ('extended_real', False): {('composite', False),\n",
       "              ('even', False),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', False),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', False),\n",
       "              ('extended_positive', False),\n",
       "              ('integer', False),\n",
       "              ('irrational', False),\n",
       "              ('negative', False),\n",
       "              ('noninteger', False),\n",
       "              ('nonnegative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('nonzero', False),\n",
       "              ('odd', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('rational', False),\n",
       "              ('real', False),\n",
       "              ('zero', False)},\n",
       "             ('algebraic', True): {('commutative', True),\n",
       "              ('complex', True),\n",
       "              ('finite', True),\n",
       "              ('infinite', False),\n",
       "              ('transcendental', False)},\n",
       "             ('extended_positive', True): {('commutative', True),\n",
       "              ('extended_negative', False),\n",
       "              ('extended_nonnegative', True),\n",
       "              ('extended_nonpositive', False),\n",
       "              ('extended_nonzero', True),\n",
       "              ('extended_real', True),\n",
       "              ('imaginary', False),\n",
       "              ('negative', False),\n",
       "              ('nonpositive', False),\n",
       "              ('zero', False)},\n",
       "             ('positive', False): {('composite', False), ('prime', False)},\n",
       "             ('finite', True): {('infinite', False)},\n",
       "             ('extended_nonnegative', False): {('composite', False),\n",
       "              ('extended_positive', False),\n",
       "              ('nonnegative', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False),\n",
       "              ('zero', False)},\n",
       "             ('extended_positive', False): {('composite', False),\n",
       "              ('positive', False),\n",
       "              ('prime', False)},\n",
       "             ('antihermitian', False): {('imaginary', False)},\n",
       "             ('extended_negative', False): {('negative', False)},\n",
       "             ('infinite', False): {('finite', True)},\n",
       "             ('nonpositive', False): {('negative', False), ('zero', False)},\n",
       "             ('odd', False): set(),\n",
       "             ('zero', False): set(),\n",
       "             ('negative', False): set(),\n",
       "             ('prime', False): set(),\n",
       "             ('composite', False): set(),\n",
       "             ('commutative', True): set(),\n",
       "             ('transcendental', False): set(),\n",
       "             ('polar', True): set(),\n",
       "             ('hermitian', True): set(),\n",
       "             ('imaginary', False): set(),\n",
       "             ('Integer', True): set(),\n",
       "             ('irrational', False): set()})"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "_assume_rules.full_implications"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`ManagedProperties` 元类将检查每个 `Basic` 类的属性，以查看是否定义了任何与假设相关的属性。其中的一个例子是 `expreal` 类中定义的 `is_extended_nonnegative = True` 属性。任何此类属性的含义将用于预先计算任何静态可知的假设。例如， `is_extended_nonnegative=True` 意味 `real=True` 等等。为存储这些假设的类创建一个 `StdFactKB` 实例，这些假设的值在此阶段已知。`StdFactKB` 实例被分配为类属性 `default_premissions`。我们可以通过"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "from sympy import Expr\n",
    "\n",
    "class A(Expr):\n",
    "    is_positive = True\n",
    "\n",
    "    def _eval_is_rational(self):\n",
    "        # Let's print something to see when this method is called...\n",
    "        print('!!! calling _eval_is_rational')\n",
    "        return True\n",
    "\n",
    "print(A.is_positive)\n",
    "print(A.is_real)  # inferred from is_positive"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "尽管在类 `A` 中定义了仅仅 `is_positive`，但是它也有一些属性，比如 `is_real`，这些属性是从 `is_positive` 中推断出来的。类 `A` 所有这些假设的集合可以在 `default_assuments` 中看到，这些假设看起来像 `dict`，但实际上是一个 `stdout/factkb` 实例:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "sympy.core.assumptions.StdFactKB"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(A.default_assumptions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'positive': True,\n",
       " 'extended_real': True,\n",
       " 'extended_nonnegative': True,\n",
       " 'nonnegative': True,\n",
       " 'finite': True,\n",
       " 'nonpositive': False,\n",
       " 'imaginary': False,\n",
       " 'nonzero': True,\n",
       " 'extended_positive': True,\n",
       " 'extended_nonpositive': False,\n",
       " 'commutative': True,\n",
       " 'infinite': False,\n",
       " 'real': True,\n",
       " 'complex': True,\n",
       " 'hermitian': True,\n",
       " 'negative': False,\n",
       " 'zero': False,\n",
       " 'extended_negative': False,\n",
       " 'extended_nonzero': True}"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.default_assumptions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当创建任何 `Basic` 子类的实例时, `Basic._new_` 将赋予它的 `_assumptions`属性, 该属性最初将引用在同一类的所有实例中共享的 `cls.default_premissions`。实例将使用它来解析任何假设查询，直到它不能给出一个确定的结果，此时将创建 `cls.default_assuments` 的副本并将其赋值给实例的 `_assumptions` 属性。该副本将用作缓存，用于存储由其 `_eval_is` 处理程序为实例计算的任何结果。\n",
    "\n",
    "当 `_assumptions` 属性无法给出相关结果时，是时候调用 `_eval_is` 处理程序了。此时将调用 `_ask()`函数。函数首先会尝试通过调用相应的方法来解析一个查询，比如是有理的，比如 `_eval_is_rational` 的。如果这给出了非空，那么结果就会被存储在 `_assumptions` 中，并且这个结果的任何影响也会被计算和存储。此时将解析查询并返回值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "!!! calling _eval_is_rational\n",
      "True\n",
      "False\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'positive': True,\n",
       " 'extended_real': True,\n",
       " 'extended_nonnegative': True,\n",
       " 'nonnegative': True,\n",
       " 'finite': True,\n",
       " 'nonpositive': False,\n",
       " 'imaginary': False,\n",
       " 'nonzero': True,\n",
       " 'extended_positive': True,\n",
       " 'extended_nonpositive': False,\n",
       " 'commutative': True,\n",
       " 'infinite': False,\n",
       " 'real': True,\n",
       " 'complex': True,\n",
       " 'hermitian': True,\n",
       " 'negative': False,\n",
       " 'zero': False,\n",
       " 'extended_negative': False,\n",
       " 'extended_nonzero': True,\n",
       " 'rational': True,\n",
       " 'irrational': False,\n",
       " 'algebraic': True,\n",
       " 'transcendental': False}"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = A()\n",
    "print(a._assumptions is A.default_assumptions)\n",
    "print(a.is_rational)\n",
    "# !!! calling _eval_is_rational\n",
    "print(a._assumptions is A.default_assumptions)\n",
    "a._assumptions # rational now shows as True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果 `eval_is_rational` 不存在或者给出 `None` ，那么 `_ask()` 将尝试所有可能性使用蕴涵规则和任何其他处理程序方法，如 `_eval_is_integer`、 `_eval_is_algebraic` 等，这些方法可能能够给出原始查询的答案。如果任何方法导致原始查询已知的确定结果，则返回该结果。否则，一旦使用处理程序的所有可能性和解决查询的隐含规则都用尽，将不会缓存和返回 `None` 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "!!! calling _eval_is_rational\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "b = A()\n",
    "print(b.is_algebraic)    # called _eval_is_rational indirectly\n",
    "!!! calling _eval_is_rational\n",
    "c = A()\n",
    "print(c.is_prime)   # called _eval_is_rational indirectly\n",
    "!!! calling _eval_is_rational\n",
    "print(c._assumptions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 注意: 在 `_ask()` 函数中，处理程序以随机顺序调用，这意味着此时的执行是不确定的。如果所有不同的处理程序方法都是一致的(即没有 bug) ，那么最终的结果仍然是确定的。然而，两个处理程序不一致的缺陷可能表现为非确定性行为，因为这种随机化可能导致处理程序在同一个程序多次运行时以不同的顺序被调用。\n",
    "\n",
    "## 局限性\n",
    "\n",
    "## 与或合并谓词\n",
    "\n",
    "在旧的假设中，我们可以很容易地将谓词与创建一个 Symbol 结合起来，例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x = Symbol('x', integer=True, positive=True)\n",
    "print(x.is_positive)\n",
    "print(x.is_integer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们也可以很容易地查询两个条件是否共同满足"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(fuzzy_and([x.is_positive, x.is_integer]))\n",
    "print(x.is_positive and x.is_integer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然而，在旧的假设中没有办法创建一个与或结合的假设谓词的符号。例如，如果我们想说 \"x 是正的或者 x 是一个整数”，那么就不可能用这些假设创建一个 Symbol。\n",
    "\n",
    "也不可能根据或例如“ is expr an expression that is positive or an integer”提出假设查询。我们可以用:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fuzzy_or([x.is_positive, x.is_integer])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然而，如果 `x` 只知道它可能是正整数或负整数，那么两个查询 `x.is_positive` 和 `x.is_integer` 都将解析为 None。这意味着查询变成了:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "print(fuzzy_or([None, None]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最终返回空。"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
  },
  "kernelspec": {
   "display_name": "Python 3.9.5 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
